import { isUndefined, isNull, PagedList, PageParams } from "mmb";
import * as store_followpb from "../grpc-client/service/store_follow_pb";
import { jsTimestampToPb, pbTimestampToJs } from "./helper";

import {
  getBgsStoreFollowOpSafely,
  getMetadata,
  getOptionsOfLight,
  wrapperGrpcError,
} from "../grpc-client/grpcAdapter";
import {
  StoreFollow,
  UpsertStoreFollowParams,
  UpdateStoreFollowParams,
  StoreFollowWithStoreAndStoreStat,
} from "./storeDeclareTypes";
import { getPub, makeTopicOfPub, wrapToMessage } from "../proxy/nsqProxy";

/****************************************************************************************/
/*                                   store_follow entity                                */
/****************************************************************************************/
const topicOfUpsertStoreFollow = "upsert-store_follow";

const StoreFollowPbToObject = (
  pb: store_followpb.StoreFollowEntity
): StoreFollow => {
  return {
    storeFollowId: `${pb.getId()}`,
    userId: `${pb.getUserId()}`,
    followedStoreId: `${pb.getFollowedStoreId()}`,
    followed: pbTimestampToJs(pb.getFollowed()),
    remark: pb.getRemark(),
  };
};

/****************************************************************************************/
/*                                   store_follow cmd                                   */
/****************************************************************************************/

export const upsertStoreFollowMq = async ({
  userId,
  followedStoreId,
  followed,
}: UpsertStoreFollowParams): Promise<boolean> => {
  return new Promise((resolve, reject) => {
    const topic = makeTopicOfPub(topicOfUpsertStoreFollow);
    const msg = wrapToMessage({
      userId: Number(userId),
      followedStoreId: Number(followedStoreId),
      followed,
    });
    // console.log('publish upsertStoreFollowMq =>', topic ,JSON.stringify(msg))
    getPub().publish(topic, msg, (err) => {
      if (err) {
        // console.log("upsertStoreFollowMq err", err);
        reject(false);
      }
      // console.log("upsertStoreFollowMq success");
      resolve(true);
    });
  });
};

export const upsertStoreFollow = async ({
  userId,
  followedStoreId,
  followed,
}: UpsertStoreFollowParams): Promise<StoreFollow> => {
  const cl = getBgsStoreFollowOpSafely();
  const req = new store_followpb.UpsertStoreFollowRequest();
  req.setUserId(Number(userId));
  req.setFollowedStoreId(Number(followedStoreId));
  req.setFollowed(jsTimestampToPb(followed));

  return new Promise((resolve, reject) => {
    cl.upsertStoreFollow(
      req,
      getMetadata(),
      getOptionsOfLight(),
      (err, res) => {
        if (!isNull(err)) {
          reject(wrapperGrpcError(err.details));
          return;
        }
        const opRet = res.getOpRet()!;
        if (!opRet.getSuccess()) {
          reject(wrapperGrpcError(opRet.getMsg()));
          return;
        }
        resolve(StoreFollowPbToObject(res.getStoreFollow()!));
      }
    );
  });
};

export const updateStoreFollow = async ({
  storeFollowId,
  remark,
}: UpdateStoreFollowParams): Promise<StoreFollow> => {
  const cl = getBgsStoreFollowOpSafely();
  const req = new store_followpb.UpdateStoreFollowRequest();

  req.setId(Number(storeFollowId));
  if (!isUndefined(remark)) {
    req.setRemark(remark);
  }

  return new Promise((resolve, reject) => {
    cl.updateStoreFollow(
      req,
      getMetadata(),
      getOptionsOfLight(),
      (err, res) => {
        if (!isNull(err)) {
          reject(wrapperGrpcError(err.details));
          return;
        }
        const opRet = res.getOpRet()!;
        if (!opRet.getSuccess()) {
          reject(wrapperGrpcError(opRet.getMsg()));
          return;
        }
        resolve(StoreFollowPbToObject(res.getStoreFollow()!));
      }
    );
  });
};

/****************************************************************************************/
/*                                   store_follow query                                 */
/****************************************************************************************/

export const getStoreFollow = async (
  storeFollowId: string
): Promise<StoreFollow> => {
  const cl = getBgsStoreFollowOpSafely();
  const req = new store_followpb.GetStoreFollowRequest();

  req.setId(Number(storeFollowId));

  return new Promise((resolve, reject) => {
    cl.getStoreFollow(req, getMetadata(), getOptionsOfLight(), (err, res) => {
      if (!isNull(err)) {
        reject(wrapperGrpcError(err.details));
        return;
      }
      const opRet = res.getOpRet()!;
      if (!opRet.getSuccess()) {
        reject(wrapperGrpcError(opRet.getMsg()));
        return;
      }
      resolve(StoreFollowPbToObject(res.getStoreFollow()!));
    });
  });
};

/****************************************************************************************/
/*                                   store_follow joins entity                          */
/****************************************************************************************/

const storeFollowWithStoreAndStoreStatPbToObject = (
  pb: store_followpb.StoreFollowWithStoreAndStoreStatEntity
): StoreFollowWithStoreAndStoreStat => {
  return {
    // store_follow
    storeFollowId: `${pb.getId()}`,
    userId: `${pb.getUserId()}`,
    followedStoreId: `${pb.getFollowedStoreId()}`,
    followed: pbTimestampToJs(pb.getFollowed()),
    remark: pb.getRemark(),

    // store
    followedStoreName: pb.getFollowedStoreName(),
    followedStorePic: pb.getFollowedStorePic(),

    // store_stat
    fansCount: pb.getFansCount(),
    publishActivityCount: pb.getPublishActivityCount(),
    spokesmanCount: pb.getSpokesmanCount(),
    endorseRequestToAuditCount: pb.getEndorseRequestToAuditCount(),
  };
};

export const listStoreFollowWithStoreAndStoreStats = async (
  userId: string,
  pager: PageParams
): Promise<PagedList<StoreFollowWithStoreAndStoreStat>> => {
  const cl = getBgsStoreFollowOpSafely();
  const req = new store_followpb.ListStoreFollowWithStoreAndStoreStatsRequest();

  req.setLimit(pager.limit);
  req.setOffset(pager.offset);
  req.setUserId(Number(userId));

  return new Promise((resolve, reject) => {
    cl.listStoreFollowWithStoreAndStoreStats(
      req,
      getMetadata(),
      getOptionsOfLight(),
      (err, res) => {
        if (!isNull(err)) {
          reject(wrapperGrpcError(err.details));
          return;
        }
        const opRet = res.getOpRet()!;
        if (!opRet.getSuccess()) {
          reject(wrapperGrpcError(opRet.getMsg()));
          return;
        }
        const ret: PagedList<StoreFollowWithStoreAndStoreStat> = {
          total: 0,
          items: [],
        };
        ret.total = res.getTotal();
        ret.items = res
          .getStoreFollowWithStoreAndStoreStatsList()
          .map((u) => storeFollowWithStoreAndStoreStatPbToObject(u));
        resolve(ret);
      }
    );
  });
};
